(*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

Copyright (c) Alexey Torgashin
*)
{$ifdef nn}begin end;{$endif}

procedure TfmMain.UpdateCaption;
var
  F: TEditorFrame;
  SName, SSession, Name1, Name2: string;
begin
  F:= CurrentFrame;
  if F=nil then exit;

  if UiOps.ShowTitlePath then
  begin
    if F.EditorsLinked then
    begin
      if F.FileName<>'' then
        SName:= msgModified[F.Ed1.Modified]+F.FileName
      else
        SName:= F.TabCaption;
    end
    else
    begin
      Name1:= F.GetFileName(F.Ed1);
      Name2:= F.GetFileName(F.Ed2);
      if Name1='' then Name1:= msgUntitledTab;
      if Name2='' then Name2:= msgUntitledTab;
      Name1:= msgModified[F.Ed1.Modified]+Name1;
      Name2:= msgModified[F.Ed2.Modified]+Name2;
      SName:= Name1+' | '+Name2;
    end;
  end
  else
    SName:= F.TabCaption;

  SSession:= ChangeFileExt(ExtractFileName(AppSessionName), '');
  if (SSession<>'') and (SSession<>'history session') then
    SSession:= ' {'+SSession+'}'
  else
    SSession:= '';

  Caption:= SName + SSession + ' - ' + msgTitle;

  Application.Title:= F.TabCaption + ' - ' + msgTitle;
end;


procedure TfmMain.UpdateStatus_ToolButton(AToolbar: TATFlatToolbar;
  ACmd: integer; AChecked, AEnabled: boolean);
var
  Btn: TATButton;
  i: integer;
begin
  for i:= 0 to AToolbar.ButtonCount-1 do
  begin
    Btn:= AToolbar.Buttons[i];
    if Btn.DataString=IntToStr(ACmd) then
    begin
      Btn.Checked:= AChecked;
      Btn.Enabled:= AEnabled;
      exit
    end;
  end;
end;


procedure TfmMain.UpdateStatus;
begin
  TimerStatusWork.Enabled:= false;
  TimerStatusWork.Enabled:= true;
end;

procedure TfmMain.UpdateSideButtonFind;
begin
  ToolbarSideMid.Buttons[0].Checked:= Assigned(fmFind) and fmFind.Visible;
end;

procedure TfmMain.UpdateStatus_RealWork;
var
  F: TEditorFrame;
  Ed: TATSynEdit;
begin
  F:= CurrentFrame;
  if F=nil then exit;
  Ed:= F.Editor;

  UpdateTabCaptionsFromFolders; //maybe it's called too often here?
  UpdateMenuChecks;
  UpdateSideButtonFind;
  UpdateStatus_ToolButton(ToolbarMain, cCommand_ToggleMinimap, Ed.OptMinimapVisible, true);
  UpdateStatus_ToolButton(ToolbarMain, cCommand_ToggleUnprinted, Ed.OptUnprintedVisible, true);

  ////Ed.UndoCount is 1 initially, but can be 0 too, so hard to check it
  //UpdateStatus_ToolButton(ToolbarMain, cCommand_Undo, false, Ed.UndoCount>0);
  //UpdateStatus_ToolButton(ToolbarMain, cCommand_Redo, false, Ed.RedoCount>0);

  UpdateStatus_ForFrame(Status, F);
end;

procedure TfmMain.UpdateStatusbarHints;
begin
  DoStatusbarHintByTag(Status, StatusbarTag_Caret, msgStatusbarHintCaret);
  DoStatusbarHintByTag(Status, StatusbarTag_Enc, msgStatusbarHintEnc);
  DoStatusbarHintByTag(Status, StatusbarTag_LineEnds, msgStatusbarHintEnds);
  DoStatusbarHintByTag(Status, StatusbarTag_Lexer, msgStatusbarHintLexer);
  DoStatusbarHintByTag(Status, StatusbarTag_SelMode, msgStatusbarHintSelMode);
  DoStatusbarHintByTag(Status, StatusbarTag_TabSize, msgStatusbarHintTabSize);
  DoStatusbarHintByTag(Status, StatusbarTag_InsOvr, msgStatusbarHintInsOvr);
  DoStatusbarHintByTag(Status, StatusbarTag_WrapMode, msgStatusbarHintWrap);
end;

procedure TfmMain.UpdateStatus_ForFrame(AStatus: TATStatus; F: TEditorFrame);
const
  cColumnMarks: array[boolean] of string = ('-', '||');
var
  Ed: TATSynEdit;
  S, fmt: string;
  Size: TPoint;
begin
  Ed:= F.Editor;

  //hide hints for pictures/viewer
  AStatus.ShowHint:= F.IsText;

  if not F.IsText then
  begin
    if F.IsBinary then
      S:= IntToStr(F.Binary.PosPercent)+'%'
    else
      S:= '';
    DoStatusbarTextByTag(AStatus, StatusbarTag_Caret, S);

    if F.IsBinary then
    begin
      S:= cEncConvNames[F.Binary.TextEncoding];
    end
    else
      S:= '';
    DoStatusbarTextByTag(AStatus, StatusbarTag_Enc, S);

    DoStatusbarTextByTag(AStatus, StatusbarTag_LineEnds, '');

    if F.IsBinary then
      S:= msgViewer+': '+msgViewerModes[F.Binary.Mode]
    else
    if F.IsPicture then
    begin
      Size:= F.PictureSizes;
      S:= Format(msgStatusPictureNxN, [Size.X, Size.Y]);
    end;
    DoStatusbarTextByTag(AStatus, StatusbarTag_Lexer, S);

    if F.IsBinary then
      S:= ''
    else
    if F.IsPicture then
      S:= IntToStr(F.PictureScale)+'%';
    DoStatusbarTextByTag(AStatus, StatusbarTag_TabSize, S);

    DoStatusbarTextByTag(AStatus, StatusbarTag_InsOvr, '');
    exit;
  end;

  //------
  case EditorGetStatusType(Ed) of
    selSmall:   fmt:= UiOps.StatusSmallSel;
    selStream:  fmt:= UiOps.StatusStreamSel;
    selCol:     fmt:= UiOps.StatusColSel;
    selCarets:  fmt:= UiOps.StatusCarets;
    else        fmt:= UiOps.StatusNoSel;
  end;
  DoStatusbarTextByTag(AStatus, StatusbarTag_Caret, EditorFormatStatus(Ed, fmt));

  //------
  S:= Ed.EncodingName;
  DoStatusbarTextByTag(AStatus, StatusbarTag_Enc, S);

  //------
  case Ed.Strings.Endings of
    cEndWin: S:= msgEndWin;
    cEndUnix: S:= msgEndUnix;
    cEndMac: S:= msgEndMac;
    else S:= '?';
  end;
  DoStatusbarTextByTag(AStatus, StatusbarTag_LineEnds, S);

  //------
  S:= F.LexerName[Ed];
  if S='' then
    S:= msgNoLexer;
  DoStatusbarTextByTag(AStatus, StatusbarTag_Lexer, S);

  //------
  if Ed.OptTabSpaces then
    S:= msgStatusbarTextSpaces+': '+IntToStr(Ed.OptTabSize)
  else
    S:= msgStatusbarTextTab+': '+IntToStr(Ed.OptTabSize);
  DoStatusbarTextByTag(AStatus, StatusbarTag_TabSize, S);

  //------
  if Ed.ModeOverwrite then
    S:= 'Ovr'
  else
    S:= 'Ins';
  DoStatusbarTextByTag(AStatus, StatusbarTag_InsOvr, S);

  //------
  DoStatusbarTextByTag(AStatus, StatusbarTag_SelMode, cColumnMarks[Ed.OptMouseColumnSelectionWithoutKey]);
  DoStatusbarTextByTag(AStatus, StatusbarTag_WrapMode, msgStatusbarWrapStates[Ord(Ed.OptWrapMode)]);

  //to update '[Read only]' in the message
  DoStatusbarTextByTag(AStatus, StatusbarTag_Msg, GetStatusbarPrefix(F)+FLastStatusbarMessage);
end;

procedure TfmMain.InitStatusbarControls;
begin
  //place StatusProgress+ButtonCancel onto Statusbar and anchor to right
  with StatusProgress do
  begin
    Parent:= Status;
    AnchorSideRight.Control:= Status;
    AnchorSideRight.Side:= asrBottom;
    AnchorSideBottom.Control:= Status;
    AnchorSideBottom.Side:= asrBottom;
    AnchorSideTop.Control:= Status;
    AnchorSideTop.Side:= asrTop;
    Anchors:= [akRight, akTop, akBottom];
    BorderSpacing.Around:= 2;
    Width:= UiOps.ProgressbarWidth;
  end;

  with LexerProgress do
  begin
    Parent:= Status;
    Align:= alRight;
    //AnchorSideRight.Control:= Status;
    //AnchorSideRight.Side:= asrRight;
    //AnchorSideTop.Control:= Status;
    //AnchorSideTop.Side:= asrTop;
    //AnchorSideBottom.Control:= Status;
    //AnchorSideBottom.Side:= asrBottom;
    //Anchors:= [akRight, akTop];
    BorderSpacing.Around:= 2;
    Kind:= gkVerticalBar;
    ShowText:= false;
    Width:= UiOps.ProgressbarHeightSmall;
  end;

  with ButtonCancel do
  begin
    Parent:= Status;
    AnchorSideRight.Control:= StatusProgress;
    AnchorSideBottom.Control:= StatusProgress;
    AnchorSideBottom.Side:= asrBottom;
    AnchorSideTop.Control:= StatusProgress;
    Anchors:= [akRight, akTop, akBottom];
    BorderSpacing.Right:= 2;
    Width:= UiOps.ProgressbarWidth;
  end;

  //UpdateLexerProgressbar(0, false);
  UpdateGlobalProgressbar(0, false);
  ButtonCancel.Hide;
end;

procedure TfmMain.UpdateCurrentFrame(AUpdatedText: boolean = false); inline;
begin
  UpdateFrameEx(CurrentFrame, AUpdatedText);
end;

procedure TfmMain.UpdateFrameEx(F: TEditorFrame; AUpdatedText: boolean); inline;
begin
  if Assigned(F) then
    F.UpdateFrame(AUpdatedText);
end;

procedure TfmMain.UpdateInputForm(Form: TForm; AndHeight: boolean=true);
var
  Ed: TATSynEdit;
  P: TPoint;
begin
  if UiOps.ListboxCentered then
  begin
    Form.Position:= poDesigned;
    P:= Frames[0].ClientToScreen(Point(0, 0));

    if Assigned(FFormTooltip) and FFormTooltip.Visible then
      Inc(P.Y, UiOps.TabHeight*2);

    Form.Left:= Left + Width div 2 - Form.Width div 2;
    Form.Top:= P.Y;
    FixFormPositionToDesktop(Form);
  end
  else
  begin
    Form.Position:= poDesigned;
    Ed:= CurrentEditor;
    P:= Ed.ClientToScreen(Point(0, 0));
    Form.Left:= P.X+(Ed.Width-Form.Width) div 2;
    Form.Top:= P.Y;
    FixFormPositionToDesktop(Form);
  end;

  if AndHeight then
    Form.Height:= AppScale(UiOps.ListboxSizeY);
end;


procedure TfmMain.UpdateEnabledAll(b: boolean);
begin
  Groups.Enabled:= b;
  if Assigned(fmFind) then
    fmFind.Enabled:= b;
end;

procedure TfmMain.UpdateAppForSearch(AStart, AEdLock, AFindMode: boolean);
var
  Frame: TEditorFrame;
  Ed: TATSynEdit;
begin
  Frame:= CurrentFrame;
  if Frame=nil then exit;
  Ed:= Frame.Editor;

  if AStart then
  begin
    FFinder.Editor:= Ed;
    FFindStop:= false;
    FFindConfirmAll:= mrNone;
    ButtonCancel.Show;
    UpdateGlobalProgressbar(0, true);
    UpdateEnabledAll(false);
    if AEdLock then
    begin
      Ed.BeginUpdate;
      Ed.Enabled:= false;
    end;
  end
  else
  begin
    ButtonCancel.Hide;
    UpdateGlobalProgressbar(0, false);
    UpdateEnabledAll(true);
    Ed.Enabled:= true;
    Ed.EndUpdate;

    if Assigned(fmFind) and fmFind.Visible and fmFind.Enabled then
      fmFind.UpdateFocus(AFindMode)
    else
      Frame.SetFocus;
  end;

  ////removed to fix issue:
  ////search fails, but OnCaret fired and Highlight Occurences gives statusbar message "hilited N matches"
  //Ed.DoEventCarets;
end;


procedure TfmMain.DoApplyFont_Text;
var
  F: TEditorFrame;
  i: integer;
begin
  if Assigned(fmConsole) then
  begin
    fmConsole.Font.Name:= EditorOps.OpFontName;
    fmConsole.Font.Size:= EditorOps.OpFontSize;
    fmConsole.Font.Quality:= EditorOps.OpFontQuality;
    fmConsole.EdInput.Font:= fmConsole.Font;
    fmConsole.EdMemo.Font:= fmConsole.Font;
  end;

  for i:= 0 to FrameCount-1 do
  begin
    F:= Frames[i];

    F.Ed1.Font.Name:= EditorOps.OpFontName;
    F.Ed1.FontItalic.Name:= EditorOps.OpFontName_i;
    F.Ed1.FontBold.Name:= EditorOps.OpFontName_b;
    F.Ed1.FontBoldItalic.Name:= EditorOps.OpFontName_bi;
    F.Ed2.Font.Name:= EditorOps.OpFontName;
    F.Ed2.FontItalic.Name:= EditorOps.OpFontName_i;
    F.Ed2.FontBold.Name:= EditorOps.OpFontName_b;
    F.Ed2.FontBoldItalic.Name:= EditorOps.OpFontName_bi;

    F.Ed1.Font.Size:= EditorOps.OpFontSize;
    F.Ed1.FontItalic.Size:= EditorOps.OpFontSize_i;
    F.Ed1.FontBold.Size:= EditorOps.OpFontSize_b;
    F.Ed1.FontBoldItalic.Size:= EditorOps.OpFontSize_bi;
    F.Ed2.Font.Size:= EditorOps.OpFontSize;
    F.Ed2.FontItalic.Size:= EditorOps.OpFontSize_i;
    F.Ed2.FontBold.Size:= EditorOps.OpFontSize_b;
    F.Ed2.FontBoldItalic.Size:= EditorOps.OpFontSize_bi;

    F.Ed1.Font.Quality:= EditorOps.OpFontQuality;
    F.Ed2.Font.Quality:= EditorOps.OpFontQuality;

    DoOps_LoadOptionsLexerSpecific(F, F.Ed1);
    if not F.EditorsLinked then
      DoOps_LoadOptionsLexerSpecific(F, F.Ed2);
  end;

  if Assigned(fmFind) then fmFind.UpdateFonts;
end;

procedure TfmMain.DoApplyFont_Ui;
var
  id: TAppPanelId;
begin
  Self.Font.Name:= UiOps.VarFontName;
  Self.Font.Size:= AppScaleFont(UiOps.VarFontSize);
  Self.Font.Color:= GetAppColor(apclTabFont);

  Groups.SetTabFont(Self.Font);
  if FloatGroups then
  begin
    GroupsF1.SetTabFont(Self.Font);
    GroupsF2.SetTabFont(Self.Font);
    GroupsF3.SetTabFont(Self.Font);
  end;

  StatusProgress.Font.Assign(Self.Font);

  //dont set font for PanelLeft/PanelBottom, id effects
  CodeTree.Tree.Font.Name:= UiOps.VarFontName;
  CodeTree.Tree.Font.Size:= AppScaleFont(UiOps.VarFontSize);

  CodeTreeFilterInput.Font.Name:= EditorOps.OpFontName;
  CodeTreeFilterInput.Font.Size:= EditorOps.OpFontSize;

  for id in TAppPanelId do
    if id<>cPaneNone then
      with AppPanels[id] do
      begin
        PanelTitle.Font.Name:= UiOps.VarFontName;
        PanelTitle.Font.Size:= AppScaleFont(UiOps.VarFontSize);
      end;

  ATFlatTheme.FontName:= UiOps.VarFontName;
  ATFlatTheme.FontSize:= UiOps.VarFontSize;
  ATFlatTheme.ScalePercents:= UiOps.Scale;
  ATFlatTheme.ScaleFontPercents:= UiOps.ScaleFont;

  if Assigned(fmFind) then
    fmFind.UpdateFonts;

  DoApplyFont_UiStatusbar;
end;

procedure TfmMain.DoApplyFont_UiStatusbar;
begin
  UpdateThemeStatusbar;
  Status.HeightInitial:= Max(UiOps.StatusHeightMin, AppScale(AppThemeStatusbar.FontSize * UiOps.StatusHeightPercents div 100));
  Status.Height:= Status.HeightInitial;
end;


procedure TfmMain.DoApplyFont_Output;
begin
  //empty now
end;

procedure TfmMain.UpdateMenuRecents(sub: TMenuItem);
var
  mi: TMenuItem;
  SName: string;
  i: integer;
begin
  if sub=nil then exit;
  sub.Clear;

  for i:= 0 to AppListRecents.Count-1 do
  begin;
    mi:= TMenuItem.Create(Self);
    SName:= IntToStr(i+1)+'.  '+
      ExtractFileName(AppListRecents[i])+'  ('+
      ExtractFileDir(AppListRecents[i])+')';
    mi.Caption:= StringReplace(SName, '&', '&&', [rfReplaceAll]);
    mi.Tag:= i;
    mi.OnClick:= @MenuRecentItemClick;
    sub.Add(mi);
  end;

  mi:= TMenuItem.Create(Self);
  mi.Caption:= '-';
  sub.Add(mi);

  mi:= TMenuItem.Create(Self);
  mi.Caption:= msgFileClearList;
  mi.OnClick:= @MenuRecentsClear;
  mi.Enabled:= AppListRecents.Count>0;
  sub.Add(mi);
end;

procedure TfmMain.UpdateMenuRecent(Ed: TATSynEdit);
var
  Frame: TEditorFrame;
  SFileName: string;
begin
  if Ed=nil then
  begin
    SAddStringToHistory('', AppListRecents, UiOps.MaxHistoryMenu);
    exit;
  end;

  Frame:= GetEditorFrame(Ed);
  if Frame=nil then exit;
  if not Frame.IsText then exit;

  SFileName:= Frame.GetFileName(Ed);
  if SFileName='' then exit;

  Frame.DoSaveHistory(Ed);

  if not Frame.InSession then
    SAddStringToHistory(
      AppCollapseHomeDirInFilename(SFileName),
      AppListRecents,
      UiOps.MaxHistoryMenu);
end;

procedure TfmMain.PopupRecentsPopup(Sender: TObject);
begin
  UpdateMenuRecents(PopupRecents.Items);
end;

procedure TfmMain.MenuRecentsPopup(Sender: TObject);
begin
  UpdateMenuRecents(mnuFileOpenSub);
end;


procedure TfmMain.DoApplyAllOps;
var
  F: TEditorFrame;
  i: integer;
begin
  DoApplyFont_Text;
  DoApplyFont_Ui;
  DoApplyFont_Output;
  DoApplyUiOps;

  for i:= 0 to FrameCount-1 do
  begin
    F:= Frames[i];
    DoApplyFrameOps(F, EditorOps, false);
    DoOps_LoadOptionsLexerSpecific(F, F.Ed1);
    if not F.EditorsLinked then
      DoOps_LoadOptionsLexerSpecific(F, F.Ed2);
  end;

  UpdateStatus;
end;

procedure TfmMain.DoApplyFrameOps(F: TEditorFrame;
  const Op: TEditorOps; AForceApply: boolean);
begin
  EditorApplyOps(F.Ed1, Op, AForceApply, not F.TabSizeChanged, Groups.Mode=gmOne, false);
  EditorApplyOps(F.Ed2, Op, AForceApply, not F.TabSizeChanged, Groups.Mode=gmOne, false);

  F.Adapter[F.Ed1].DynamicHiliteEnabled:= Op.OpLexerDynamicHiliteEnabled;
  F.Adapter[F.Ed1].DynamicHiliteMaxLines:= Op.OpLexerDynamicHiliteMaxLines;

  F.Adapter[F.Ed2].DynamicHiliteEnabled:= Op.OpLexerDynamicHiliteEnabled;
  F.Adapter[F.Ed2].DynamicHiliteMaxLines:= Op.OpLexerDynamicHiliteMaxLines;

  if not F.BracketHiliteUserChanged then
    F.BracketHilite:= Op.OpBracketHilite;
  F.BracketSymbols:= Op.OpBracketSymbols;
  F.BracketDistance:= Op.OpBracketDistance;

  F.Ed1.Update;
  if F.Splitted then
    F.Ed2.Update;

  UpdateStatus;
end;

procedure TfmMain.UpdateMenuItemHint(mi: TMenuItem; const AHint: string);
begin
  if not Assigned(mi) then exit;

  if mi.Tag=0 then
    mi.Tag:= PtrInt(TAppMenuProps.Create);

  TAppMenuProps(mi.Tag).CommandString:= AHint;
end;

procedure TfmMain.UpdateMenuItemHotkey(mi: TMenuItem; cmd: integer);
begin
  if not Assigned(mi) then exit;

  if mi.Tag=0 then
    mi.Tag:= PtrInt(TAppMenuProps.Create);

  TAppMenuProps(mi.Tag).CommandCode:= cmd;
  mi.OnClick:= @MenuMainClick;

  {$ifndef LCLQT5}
  //seems Qt5 version has slowdown because of MainMenu hotkeys?

  //if Copy/Paste/SelectAll hotkeys set in MainMenu, Qt5 version cannot handle them in Console/Find/Replace
  if (cmd<>cCommand_ClipboardCopy) and
    (cmd<>cCommand_ClipboardPaste) and
    (cmd<>cCommand_ClipboardCut) and
    (cmd<>cCommand_Undo) and
    (cmd<>cCommand_Redo) and
    (cmd<>cCommand_SelectAll) then
    mi.ShortCut:= AppKeymapMain.GetShortcutFromCommand(cmd);

  //don't set Esc here: for OSX/ Qt, else Esc blocked in Find/ Goto/ closing app
  if mi.Shortcut=AppShortcutEscape then
    mi.ShortCut:= 0;
  //don't allow Shift+Tab in menu: it blocks tabbing in Find/Replace
  if mi.Shortcut=AppShortcutShiftTab then
    mi.ShortCut:= 0;
  {$endif}
end;

procedure TfmMain.UpdateMenuItemAltObject(mi: TMenuItem; cmd: integer);
  //
  procedure DoSave(mi: TMenuItem; var save: TATMenuItemsAlt); inline;
  begin
    if save.active0 then save.item0:= mi else save.item1:= mi;
    save.active0:= not save.active0;
  end;
  //
begin
  //MsgLogConsole('cmd'+inttostr(cmd));
  if cmd>0 then
  case cmd of
    cCommand_ToggleWordWrap : DoSave(mi, mnuViewWrap_Alt);
    cCommand_ToggleLineNums : DoSave(mi, mnuViewNums_Alt);
    cCommand_ToggleFolding : DoSave(mi, mnuViewFold_Alt);
    cCommand_ToggleRuler : DoSave(mi, mnuViewRuler_Alt);
    cCommand_ToggleMinimap : DoSave(mi, mnuViewMinimap_Alt);
    cCommand_ToggleMicromap : DoSave(mi, mnuViewMicromap_Alt);
    cCommand_ToggleUnprinted : DoSave(mi, mnuViewUnpriShow_Alt);
    cCommand_ToggleUnprintedSpaces : DoSave(mi, mnuViewUnpriSpaces_Alt);
    cCommand_ToggleUnprintedSpacesTrailing : DoSave(mi, mnuViewUnpriSpacesTail_Alt);
    cCommand_ToggleUnprintedEnds : DoSave(mi, mnuViewUnpriEnds_Alt);
    cCommand_ToggleUnprintedEndDetails : DoSave(mi, mnuViewUnpriEndsDet_Alt);

    cmd_SplitTabNo: DoSave(mi, mnuViewSplitNo_Alt);
    cmd_SplitTabVert: DoSave(mi, mnuViewSplitV_Alt);
    cmd_SplitTabHorz: DoSave(mi, mnuViewSplitH_Alt);

    cmd_ToggleToolbar : DoSave(mi, mnuViewToolbar_Alt);
    cmd_ToggleStatusbar : DoSave(mi, mnuViewStatus_Alt);
    cmd_ToggleFullScreen : DoSave(mi, mnuViewFullscr_Alt);
    cmd_ToggleDistractionFree : DoSave(mi, mnuViewDistFree_Alt);
    cmd_ToggleSidePanel : DoSave(mi, mnuViewSide_Alt);
    cmd_ToggleBottomPanel : DoSave(mi, mnuViewBottom_Alt);
    cmd_ToggleFloatSide : DoSave(mi, mnuViewFloatSide_Alt);
    cmd_ToggleFloatBottom : DoSave(mi, mnuViewFloatBottom_Alt);
    cmd_ToggleOnTop: DoSave(mi, mnuViewOnTop_Alt);

    cmd_Groups1 : DoSave(mi, mnuGr1_Alt);
    cmd_Groups2horz : DoSave(mi, mnuGr2H_Alt);
    cmd_Groups2vert : DoSave(mi, mnuGr2V_Alt);
    cmd_Groups3horz : DoSave(mi, mnuGr3H_Alt);
    cmd_Groups3vert : DoSave(mi, mnuGr3V_Alt);
    cmd_Groups3plus : DoSave(mi, mnuGr1p2V_Alt);
    cmd_Groups3plushorz : DoSave(mi, mnuGr1p2H_Alt);
    cmd_Groups4horz : DoSave(mi, mnuGr4H_Alt);
    cmd_Groups4vert : DoSave(mi, mnuGr4V_Alt);
    cmd_Groups4grid : DoSave(mi, mnuGr4G_Alt);
    cmd_Groups6horz : DoSave(mi, mnuGr6H_Alt);
    cmd_Groups6vert : DoSave(mi, mnuGr6V_Alt);
    cmd_Groups6grid : DoSave(mi, mnuGr6_Alt);
  end;
end;

procedure TfmMain.UpdateMenuHotkeys;
begin
  UpdateMenuItemHotkey(mnuApple_About, cmd_HelpAbout);

  UpdateMenuItemHotkey(mnuFileEnc, cmd_MenuEnc);
  UpdateMenuItemHotkey(mnuFileEndWin, cmd_LineEndWin);
  UpdateMenuItemHotkey(mnuFileEndUn, cmd_LineEndUnix);
  UpdateMenuItemHotkey(mnuFileEndMac, cmd_LineEndMac);

  UpdateMenuItemHotkey(mnuFileNew, cmd_FileNew);
  UpdateMenuItemHotkey(mnuFileNewMenu, cmd_FileNewMenu);
  UpdateMenuItemHotkey(mnuFileOpen, cmd_FileOpen);
  UpdateMenuItemHotkey(mnuFileOpenDir, cmd_FileOpenFolder);
  UpdateMenuItemHotkey(mnuFileReopen, cmd_FileReopen);
  UpdateMenuItemHotkey(mnuFileSave, cmd_FileSave);
  UpdateMenuItemHotkey(mnuFileSaveAs, cmd_FileSaveAs);
  UpdateMenuItemHotkey(mnuFileSaveAll, cmd_FileSaveAll);
  UpdateMenuItemHotkey(mnuFileClose, cmd_FileClose);
  UpdateMenuItemHotkey(mnuFileCloseAll, cmd_FileCloseAll);
  UpdateMenuItemHotkey(mnuFileCloseOther, cmd_FileCloseOtherThis);
  UpdateMenuItemHotkey(mnuFileCloseDel, cmd_FileCloseAndDelete);
  UpdateMenuItemHotkey(mnuFileExit, cmd_FileExit);

  UpdateMenuItemHotkey(mnuSelAll, cCommand_SelectAll);
  UpdateMenuItemHotkey(mnuSelSplit, cCommand_SelectSplitToLines);
  UpdateMenuItemHotkey(mnuSelExtLine, cCommand_SelectExtendByLine);
  UpdateMenuItemHotkey(mnuSelExtWord, cmd_SelectExpandToWord);
  UpdateMenuItemHotkey(mnuSelInvert, cCommand_SelectInverted);

  UpdateMenuItemHotkey(mnuCaretsCancel, cCommand_Cancel);
  UpdateMenuItemHotkey(mnuCaretsUp1Line, cCommand_CaretsExtendUpLine);
  UpdateMenuItemHotkey(mnuCaretsUp1Page, cCommand_CaretsExtendUpPage);
  UpdateMenuItemHotkey(mnuCaretsUpBegin, cCommand_CaretsExtendUpToTop);
  UpdateMenuItemHotkey(mnuCaretsDown1Line, cCommand_CaretsExtendDownLine);
  UpdateMenuItemHotkey(mnuCaretsDown1Page, cCommand_CaretsExtendDownPage);
  UpdateMenuItemHotkey(mnuCaretsDownEnd, cCommand_CaretsExtendDownToEnd);

  UpdateMenuItemHotkey(mnuEditUndo, cCommand_Undo);
  UpdateMenuItemHotkey(mnuEditRedo, cCommand_Redo);
  UpdateMenuItemHotkey(mnuEditCut, cCommand_ClipboardCut);
  UpdateMenuItemHotkey(mnuEditCopy, cCommand_ClipboardCopy);
  UpdateMenuItemHotkey(mnuEditPaste, cCommand_ClipboardPaste);
  UpdateMenuItemHotkey(mnuEditDel, cCommand_TextDeleteSelection);

  UpdateMenuItemHotkey(mnuEditCopyLine, cmd_CopyLine);
  UpdateMenuItemHotkey(mnuEditCopyAppend, cCommand_ClipboardCopyAdd);
  UpdateMenuItemHotkey(mnuEditCopyFFull, cmd_CopyFilenameFull);
  UpdateMenuItemHotkey(mnuEditCopyFDir, cmd_CopyFilenameDir);
  UpdateMenuItemHotkey(mnuEditCopyFName, cmd_CopyFilenameName);

  UpdateMenuItemHotkey(mnuEditIndent, cCommand_TextIndent);
  UpdateMenuItemHotkey(mnuEditUnindent, cCommand_TextUnindent);
  UpdateMenuItemHotkey(mnuEditTrim, cCommand_TextTrimSpacesAll);
  UpdateMenuItemHotkey(mnuEditTrimL, cCommand_TextTrimSpacesLeft);
  UpdateMenuItemHotkey(mnuEditTrimR, cCommand_TextTrimSpacesRight);

  UpdateMenuItemHotkey(mnuEditTabToSp, cmd_ConvertTabsToSpaces);
  UpdateMenuItemHotkey(mnuEditSpToTab, cmd_ConvertSpacesToTabsLeading);

  UpdateMenuItemHotkey(mnuEditLineDel, cCommand_TextDeleteLine);
  UpdateMenuItemHotkey(mnuEditLineDup, cCommand_TextDuplicateLine);
  UpdateMenuItemHotkey(mnuEditLineMoveUp, cCommand_MoveSelectionUp);
  UpdateMenuItemHotkey(mnuEditLineMoveDown, cCommand_MoveSelectionDown);

  UpdateMenuItemHotkey(mnuCaseUp, cCommand_TextCaseUpper);
  UpdateMenuItemHotkey(mnuCaseLow, cCommand_TextCaseLower);
  UpdateMenuItemHotkey(mnuCaseTitle, cCommand_TextCaseTitle);
  UpdateMenuItemHotkey(mnuCaseInvert, cCommand_TextCaseInvert);
  UpdateMenuItemHotkey(mnuCaseSent, cCommand_TextCaseSentence);

  UpdateMenuItemHotkey(mnuEditCharmap, cmd_DialogCharMap);

  UpdateMenuItemHotkey(mnuFindDlg, cmd_DialogFind);
  UpdateMenuItemHotkey(mnuFindRepDialog, cmd_DialogReplace);
  UpdateMenuItemHotkey(mnuFindNext, cmd_FindNext);
  UpdateMenuItemHotkey(mnuFindPrev, cmd_FindPrev);
  UpdateMenuItemHotkey(mnuFindWordNext, cmd_FindCurWordNext);
  UpdateMenuItemHotkey(mnuFindWordPrev, cmd_FindCurWordPrev);

  UpdateMenuItemHotkey(mnuGotoLine, cmd_DialogGoto);
  UpdateMenuItemHotkey(mnuGotoBm, cmd_DialogGotoBookmark);

  UpdateMenuItemHotkey(mnuBmNext, cmd_BookmarkGotoNext);
  UpdateMenuItemHotkey(mnuBmPrev, cmd_BookmarkGotoPrev);
  UpdateMenuItemHotkey(mnuBmToggle, cmd_BookmarkToggle);
  UpdateMenuItemHotkey(mnuBmInvert, cmd_BookmarkInvertAll);
  UpdateMenuItemHotkey(mnuBmPlaceCarets, cmd_BookmarkPlaceCarets);
  UpdateMenuItemHotkey(mnuBmPlaceOnCarets, cmd_BookmarkPlaceBookmarksOnCarets);
  UpdateMenuItemHotkey(mnuBmClear, cmd_BookmarkClearAll);
  UpdateMenuItemHotkey(mnuBmCopyLines, cmd_BookmarkCopyMarkedLines);
  UpdateMenuItemHotkey(mnuBmDeleteLines, cmd_BookmarkDeleteMarkedLines);

  UpdateMenuItemHotkey(mnuGr1, cmd_Groups1);
  UpdateMenuItemHotkey(mnuGr2V, cmd_Groups2vert);
  UpdateMenuItemHotkey(mnuGr2H, cmd_Groups2horz);
  UpdateMenuItemHotkey(mnuGr3V, cmd_Groups3vert);
  UpdateMenuItemHotkey(mnuGr3H, cmd_Groups3horz);
  UpdateMenuItemHotkey(mnuGr1p2V, cmd_Groups3plus);
  UpdateMenuItemHotkey(mnuGr1p2H, cmd_Groups3plushorz);
  UpdateMenuItemHotkey(mnuGr4V, cmd_Groups4vert);
  UpdateMenuItemHotkey(mnuGr4H, cmd_Groups4horz);
  UpdateMenuItemHotkey(mnuGr4G, cmd_Groups4grid);
  UpdateMenuItemHotkey(mnuGr6V, cmd_Groups6vert);
  UpdateMenuItemHotkey(mnuGr6H, cmd_Groups6horz);
  UpdateMenuItemHotkey(mnuGr6, cmd_Groups6grid);

  UpdateMenuItemHotkey(mnuViewSplitNo, cmd_SplitTabNo);
  UpdateMenuItemHotkey(mnuViewSplitV, cmd_SplitTabVert);
  UpdateMenuItemHotkey(mnuViewSplitH, cmd_SplitTabHorz);

  UpdateMenuItemHotkey(mnuViewWrap, cCommand_ToggleWordWrap);
  UpdateMenuItemHotkey(mnuViewNums, cCommand_ToggleLineNums);
  UpdateMenuItemHotkey(mnuViewFold, cCommand_ToggleFolding);
  UpdateMenuItemHotkey(mnuViewRuler, cCommand_ToggleRuler);
  UpdateMenuItemHotkey(mnuViewMinimap, cCommand_ToggleMinimap);
  UpdateMenuItemHotkey(mnuViewMicromap, cCommand_ToggleMicromap);

  UpdateMenuItemHotkey(mnuViewUnpriShow, cCommand_ToggleUnprinted);
  UpdateMenuItemHotkey(mnuViewUnpriSpaces, cCommand_ToggleUnprintedSpaces);
  UpdateMenuItemHotkey(mnuViewUnpriSpacesTail, cCommand_ToggleUnprintedSpacesTrailing);
  UpdateMenuItemHotkey(mnuViewUnpriEnds, cCommand_ToggleUnprintedEnds);
  UpdateMenuItemHotkey(mnuViewUnpriEndsDet, cCommand_ToggleUnprintedEndDetails);

  UpdateMenuItemHotkey(mnuViewFullscr, cmd_ToggleFullScreen);
  UpdateMenuItemHotkey(mnuViewDistFree, cmd_ToggleDistractionFree);
  UpdateMenuItemHotkey(mnuViewSidebar, cmd_ToggleSidebar);
  UpdateMenuItemHotkey(mnuViewSide, cmd_ToggleSidePanel);
  UpdateMenuItemHotkey(mnuViewBottom, cmd_ToggleBottomPanel);
  UpdateMenuItemHotkey(mnuViewFloatSide, cmd_ToggleFloatSide);
  UpdateMenuItemHotkey(mnuViewFloatBottom, cmd_ToggleFloatBottom);
  UpdateMenuItemHotkey(mnuViewToolbar, cmd_ToggleToolbar);
  UpdateMenuItemHotkey(mnuViewStatus, cmd_ToggleStatusbar);
  UpdateMenuItemHotkey(mnuViewOnTop, cmd_ToggleOnTop);
  UpdateMenuItemHotkey(mnuLexers, cmd_DialogLexerMenu);

  UpdateMenuItemHotkey(mnuOpDefault, cmd_OpsOpenDefault);
  UpdateMenuItemHotkey(mnuOpUser, cmd_OpsOpenUser);
  UpdateMenuItemHotkey(mnuOpDefaultUser, cmd_OpsOpenDefaultAndUser);
  UpdateMenuItemHotkey(mnuOpLexer, cmd_OpsOpenLexerSpecific);
  //UpdateMenuItemHotkey(mnuOpKeys, cmd_HelpHotkeys);

  UpdateMenuItemHotkey(mnuFontText, cmd_OpsFontText);
  UpdateMenuItemHotkey(mnuFontUi, cmd_OpsFontUi);
  UpdateMenuItemHotkey(mnuFontOutput, cmd_OpsFontOutput);

  UpdateMenuItemHotkey(mnuOpLexProp, cmd_DialogLexerProp);
  UpdateMenuItemHotkey(mnuOpLexLib, cmd_DialogLexerLib);
  UpdateMenuItemHotkey(mnuOpLexMap, cmd_DialogLexerStyleMap);
  UpdateMenuItemHotkey(mnuOpThemeUi, cmd_DialogThemeUi);
  UpdateMenuItemHotkey(mnuOpThemeSyntax, cmd_DialogThemeSyntax);
  UpdateMenuItemHotkey(mnuOpThemes, cmd_ChooseThemeUI);
  UpdateMenuItemHotkey(mnuOpLangs, cmd_ChooseTranslation);

  UpdateMenuItemHotkey(mnuHelpCmd, cmd_DialogCommands);
  UpdateMenuItemHotkey(mnuHelpForum, cmd_HelpForum);
  UpdateMenuItemHotkey(mnuHelpWiki, cmd_HelpWiki);
  UpdateMenuItemHotkey(mnuHelpIssues, cmd_HelpIssues);
  UpdateMenuItemHotkey(mnuHelpCheckUpd, cmd_HelpCheckUpdates);
  UpdateMenuItemHotkey(mnuHelpAbout, cmd_HelpAbout);
end;

procedure TfmMain.UpdateEditorTabsize(AValue: integer);
var
  F: TEditorFrame;
  Ed: TATSynEdit;
begin
  F:= CurrentFrame;
  if F=nil then exit;
  Ed:= F.Editor;

  case AValue of
    -1:
      Ed.OptTabSpaces:= true;
    -2:
      Ed.OptTabSpaces:= false;
    -3:
      Ed.OptTabSpaces:= not Ed.OptTabSpaces;
    1..100:
      Ed.OptTabSize:= AValue;
  end;

  F.TabSizeChanged:= true;

  UpdateFrameEx(F, false);
  UpdateStatus;
end;

procedure TfmMain.UpdateMenuItemChecked(mi: TMenuItem; saved: TATMenuItemsAlt; AValue: boolean);
begin
  if Assigned(mi) then mi.Checked:= AValue;
  if Assigned(saved.item0) then saved.item0.Checked:= AValue;
  if Assigned(saved.item1) then saved.item1.Checked:= AValue;
end;

procedure TfmMain.UpdateMenuChecks;
var
  F: TEditorFrame;
  Ed: TATSynEdit;
begin
  F:= CurrentFrame;
  if F=nil then exit;
  Ed:= F.Editor;

  UpdateMenuItemChecked(mnuViewWrap, mnuViewWrap_Alt, Ed.OptWrapMode<>cWrapOff);
  UpdateMenuItemChecked(mnuViewNums, mnuViewNums_Alt, Ed.Gutter.Items[Ed.GutterBandNumbers].Visible);
  UpdateMenuItemChecked(mnuViewFold, mnuViewFold_Alt, Ed.Gutter.Items[Ed.GutterBandFolding].Visible);
  UpdateMenuItemChecked(mnuViewRuler, mnuViewRuler_Alt, Ed.OptRulerVisible);
  UpdateMenuItemChecked(mnuViewMinimap, mnuViewMinimap_Alt, Ed.OptMinimapVisible);
  UpdateMenuItemChecked(mnuViewMicromap, mnuViewMicromap_Alt, Ed.OptMicromapVisible);

  UpdateMenuItemChecked(mnuViewUnpriShow, mnuViewUnpriShow_Alt, Ed.OptUnprintedVisible);
  UpdateMenuItemChecked(mnuViewUnpriSpaces, mnuViewUnpriSpaces_Alt, Ed.OptUnprintedSpaces);
  UpdateMenuItemChecked(mnuViewUnpriSpacesTail, mnuViewUnpriSpacesTail_Alt, Ed.OptUnprintedSpacesTrailing);
  UpdateMenuItemChecked(mnuViewUnpriEnds, mnuViewUnpriEnds_Alt, Ed.OptUnprintedEnds);
  UpdateMenuItemChecked(mnuViewUnpriEndsDet, mnuViewUnpriEndsDet_Alt, Ed.OptUnprintedEndsDetails);

  UpdateMenuItemChecked(mnuViewSplitNo, mnuViewSplitNo_Alt, not F.Splitted);
  UpdateMenuItemChecked(mnuViewSplitV, mnuViewSplitV_Alt, F.Splitted and not F.SplitHorz);
  UpdateMenuItemChecked(mnuViewSplitH, mnuViewSplitH_Alt, F.Splitted and F.SplitHorz);

  UpdateMenuItemChecked(mnuViewToolbar, mnuViewToolbar_Alt, ShowToolbar);
  UpdateMenuItemChecked(mnuViewStatus, mnuViewStatus_Alt, ShowStatus);
  UpdateMenuItemChecked(mnuViewFullscr, mnuViewFullscr_Alt, ShowFullscreen);
  UpdateMenuItemChecked(mnuViewDistFree, mnuViewDistFree_Alt, ShowDistractionFree);
  UpdateMenuItemChecked(mnuViewSidebar, mnuViewSidebar_Alt, ShowSideBar);
  UpdateMenuItemChecked(mnuViewSide, mnuViewSide_Alt, AppPanels[cPaneSide].Visible);
  UpdateMenuItemChecked(mnuViewBottom, mnuViewBottom_Alt, AppPanels[cPaneOut].Visible);
  UpdateMenuItemChecked(mnuViewFloatSide, mnuViewFloatSide_Alt, AppPanels[cPaneSide].Floating);
  UpdateMenuItemChecked(mnuViewFloatBottom, mnuViewFloatBottom_Alt, AppPanels[cPaneOut].Floating);
  UpdateMenuItemChecked(mnuViewOnTop, mnuViewOnTop_Alt, ShowOnTop);

  UpdateMenuItemChecked(mnuGr1, mnuGr1_Alt, Groups.Mode= gmOne);
  UpdateMenuItemChecked(mnuGr2V, mnuGr2V_Alt, Groups.Mode= gm2v);
  UpdateMenuItemChecked(mnuGr2H, mnuGr2H_Alt, Groups.Mode= gm2h);
  UpdateMenuItemChecked(mnuGr3V, mnuGr3V_Alt, Groups.Mode= gm3v);
  UpdateMenuItemChecked(mnuGr3H, mnuGr3H_Alt, Groups.Mode= gm3h);
  UpdateMenuItemChecked(mnuGr1p2V, mnuGr1p2V_Alt, Groups.Mode= gm1plus2v);
  UpdateMenuItemChecked(mnuGr1p2H, mnuGr1p2H_Alt, Groups.Mode= gm1plus2h);
  UpdateMenuItemChecked(mnuGr4V, mnuGr4V_Alt, Groups.Mode= gm4v);
  UpdateMenuItemChecked(mnuGr4H, mnuGr4H_Alt, Groups.Mode= gm4h);
  UpdateMenuItemChecked(mnuGr4G, mnuGr4G_Alt, Groups.Mode= gm4Grid);
  UpdateMenuItemChecked(mnuGr6V, mnuGr6V_Alt, Groups.Mode= gm6v);
  UpdateMenuItemChecked(mnuGr6H, mnuGr6H_Alt, Groups.Mode= gm6h);
  UpdateMenuItemChecked(mnuGr6, mnuGr6_Alt, Groups.Mode= gm6Grid);
end;

procedure TfmMain.UpdateTreeContents;
begin
  TimerTreeFill.Enabled:= false;
  TimerTreeFill.Enabled:= true;
end;

procedure TfmMain.UpdateTreeFilter;
begin
  CodeTreeFilter.InvalidateFilter;
end;

procedure TfmMain.UpdateTree(AFill: boolean; AConsiderTreeVisible: boolean;
  AForceUpdateAll: boolean);
var
  Frame: TEditorFrame;
  Ed: TATSynEdit;
  Ada: TATAdapterEControl;
begin
  if AConsiderTreeVisible then
    if not AppPanels[cPaneSide].Visible then exit;

  Frame:= CurrentFrame;
  if Frame=nil then exit;
  Ed:= Frame.Editor;

  Ada:= Frame.Adapter[Ed];
  if (Ada=nil) or (Ada.AnClient=nil) then
  begin
    ClearTreeviewWithData(CodeTree.Tree);
    exit
  end;

  if not Frame.EnabledCodeTree[Ed] then
  begin
    //don't clear tree, it may be filled by plugin
    UpdateTreeSelection(Frame, Ed); //needed even for disabled CodeTree (for plugins)
    exit;
  end;

  {
  NRanges:= Ada.AnClient.RangeCount;
  if (NRanges>UiOps.MaxRangesForCodeTree) then
  begin
    ClearTreeviewWithData(CodeTree.Tree);
    exit;
  end;
  }

  while Ada.TreeBusy do
  begin
    Application.ProcessMessages;
    if Application.Terminated then exit;
  end;

  if AForceUpdateAll then
  begin
    Ada.InvokeParser(Ed, true);
    //Ed.DoEventChange; //why it was needed?
  end;

 if AFill then
 begin
   InitImageListCodetree;

   if UiOps.TreeShowIcons then
     CodeTree.Tree.Images:= ImageListTree
   else
     CodeTree.Tree.Images:= nil;

   FCodetreeModifiedVersion:= Ed.Strings.ModifiedVersion;
   if not DoPyTreeHelper(Frame) then
   begin
     if not Assigned(FCodetreeBuffer) then
       FCodetreeBuffer:= TTreeView.Create(Self);
     Ada.TreeFill(FCodetreeBuffer);

     if FCodetreeBuffer.Items.Count>0 then
       DoTreeviewCopy(FCodetreeBuffer, Frame.CachedTreeview[Ed]);

     //Lazarus dont sort new items
     if CodeTree.Tree.SortType<>stNone then
       FCodetreeBuffer.AlphaSort;

     DoTreeviewCopy(FCodetreeBuffer, CodeTree.Tree);
     CodeTree.SourceObject:= Ed;

     //force update scrollbar
     CodeTree.Tree.Font.Size:= AppScaleFont(UiOps.VarFontSize);
     CodeTree.Tree.Perform(CM_CHANGED, 0, 0);
    end;
  end;

  UpdateTreeFilter;
  UpdateTreeSelection(Frame, Ed);
end;

procedure TfmMain.UpdateTreeSelection(Frame: TEditorFrame; Ed: TATSynEdit);
var
  Caret: TATCaretItem;
begin
  if not UiOps.TreeAutoSync then exit;

  if Ed.Carets.Count=0 then exit;
  Caret:= Ed.Carets[0];

  CodetreeSelectItemForPosition(
    CodeTree.Tree,
    Caret.PosX, Caret.PosY
    );
end;

procedure TfmMain.UpdateMenuEnc(AMenu: TMenuItem);
  //
  procedure DoAdd(AMenu: TMenuItem; Sub, SName: string; AReloadFile: boolean);
  var
    mi, miSub: TMenuItem;
    n: integer;
  begin
    miSub:= nil;
    if Sub='eu' then Sub:= msgEncEuropean else
     if Sub='as' then Sub:= msgEncAsian else
      if Sub='mi' then Sub:= msgEncMisc;

    if Sub<>'' then
    begin
      n:= AMenu.IndexOfCaption(Sub);
      if n<0 then
      begin
        mi:= TMenuItem.Create(Self);
        mi.Caption:= Sub;
        AMenu.Add(mi);
        n:= AMenu.IndexOfCaption(Sub);
      end;
      miSub:= AMenu.Items[n]
    end;

    if miSub=nil then miSub:= AMenu;
    mi:= TMenuItem.Create(Self);
    mi.Caption:= SName;

    if AReloadFile then
      mi.OnClick:= @MenuEncWithReloadClick
    else
      mi.OnClick:= @MenuEncNoReloadClick;

    miSub.Add(mi);
  end;
  //
var
  miReload, miNoReload: TMenuItem;
  i: integer;
begin
  if AMenu=nil then exit;
  AMenu.Clear;

  miReload:= TMenuItem.Create(Self);
  miReload.Caption:= msgEncReloadAs;
  miReload.Hint:= 'enc_reload';
  miNoReload:= TMenuItem.Create(Self);
  miNoReload.Caption:= msgEncConvertTo;
  miNoReload.Hint:= 'enc_noreload';

  AMenu.Add(miReload);
  AMenu.Add(miNoReload);

  for i:= Low(AppEncodings) to High(AppEncodings) do
  begin
    DoAdd(miReload, AppEncodings[i].Sub, AppEncodings[i].Name, true);
    DoAdd(miNoReload, AppEncodings[i].Sub, AppEncodings[i].Name, false);
  end;
end;


procedure TfmMain.UpdateStatusbarPanelsFromString(const AText: string);
var
  SPanel, SItem: string;
  NIndex, NSize, NTag: integer;
  Al: TAlignment;
  SepAll, SepItem: TATStringSeparator;
  bAutoSize, bStretch, bHotTrack: boolean;
begin
  //complex deletion of panels, touch only CudaText std panels
  for NTag:= StatusbarTag_Caret{minimal tag} to StatusbarTag_Msg{maximal tag} do
  begin
    NIndex:= Status.FindPanel(NTag);
    Status.DeletePanel(NIndex);
  end;

  SepAll.Init(AText, '|');
  repeat
    if not SepAll.GetItemStr(SPanel) then Break;

    SepItem.Init(SPanel);
    NTag:= 0;
    NIndex:= Status.PanelCount;
    bStretch:= false;
    bHotTrack:= false;

    SepItem.GetItemStr(SItem);
    case SItem of
      'caret':   begin NTag:= StatusbarTag_Caret; bHotTrack:= true; end;
      'enc':     begin NTag:= StatusbarTag_Enc; bHotTrack:= true; end;
      'ends':    begin NTag:= StatusbarTag_LineEnds; bHotTrack:= true; end;
      'lexer':   begin NTag:= StatusbarTag_Lexer; bHotTrack:= true; end;
      'tabsize': begin NTag:= StatusbarTag_TabSize; bHotTrack:= true; end;
      'ins':     begin NTag:= StatusbarTag_InsOvr; bHotTrack:= true; end;
      'msg':     begin NTag:= StatusbarTag_Msg; bStretch:= true; end;
      'selmode': begin NTag:= StatusbarTag_SelMode; bHotTrack:= true; end;
      'wrap':    begin NTag:= StatusbarTag_WrapMode; bHotTrack:= true; end;
      else Continue;
    end;

    SepItem.GetItemStr(SItem);
    bAutoSize:= SItem='A';
    if bAutoSize then
      Al:= taLeftJustify
    else
      Al:= AppStringToAlignment(SItem);

    SepItem.GetItemStr(SItem);
    NSize:= Max(16, StrToIntDef(SItem, 200));

    Status.AddPanel(-1, NSize, Al, '', -1, NTag, bAutoSize, bStretch, clNone, bHotTrack);
  until false;
end;


procedure TfmMain.DoInvalidateEditors;
var
  F: TEditorFrame;
  i: integer;
begin
  for i:= 0 to FrameCount-1 do
  begin
    F:= Frames[i];
    if not F.Visible then Continue;
    F.Ed1.Invalidate;
    F.Ed2.Invalidate;
    F.Splitter.Invalidate;
  end;

  Groups.Splitter1.Invalidate;
  Groups.Splitter2.Invalidate;
  Groups.Splitter3.Invalidate;
  Groups.Splitter4.Invalidate;
  Groups.Splitter5.Invalidate;
end;


procedure TfmMain.InitToolbar;
begin
  ToolbarMain.Images:= TImageList.Create(Self);
  ToolbarMain.Images.AllocBy:= 20;

  ToolbarMain.AddButton(0, @DoToolbarClick, 'f_new', 'New file', IntToStr(cmd_FileNew), false);
  ToolbarMain.AddDropdown(-1, nil, @DoFileNewMenu);
  ToolbarMain.AddButton(1, @DoToolbarClick, 'f_open', 'Open file', IntToStr(cmd_FileOpen), false);
  ToolbarMain.AddDropdown(-1, PopupRecents);
  ToolbarMain.AddButton(2, @DoToolbarClick, 'f_save', 'Save file', IntToStr(cmd_FileSave), false);
  ToolbarMain.AddSep;
  ToolbarMain.AddButton(3, @DoToolbarClick, 'e_cut', 'Cut', IntToStr(cCommand_ClipboardCut), false);
  ToolbarMain.AddButton(4, @DoToolbarClick, 'e_copy', 'Copy', IntToStr(cCommand_ClipboardCopy), false);
  ToolbarMain.AddButton(5, @DoToolbarClick, 'e_paste', 'Paste', IntToStr(cCommand_ClipboardPaste), false);
  ToolbarMain.AddButton(6, @DoToolbarClick, 'e_undo', 'Undo', IntToStr(cCommand_Undo), false);
  ToolbarMain.AddButton(7, @DoToolbarClick, 'e_redo', 'Redo', IntToStr(cCommand_Redo), false);
  ToolbarMain.AddSep;
  ToolbarMain.AddButton(8, @DoToolbarClick, 'unpri', 'Toggle unprinted chars', IntToStr(cCommand_ToggleUnprinted), false);
  ToolbarMain.AddButton(9, @DoToolbarClick, 'map', 'Toggle minimap', IntToStr(cCommand_ToggleMinimap), false);
  ToolbarMain.AddSep;
  ToolbarMain.AddButton(10, @DoToolbarClick, 'indent', 'Indent block', IntToStr(cCommand_TextIndent), false);
  ToolbarMain.AddButton(11, @DoToolbarClick, 'unindent', 'Unindent block', IntToStr(cCommand_TextUnIndent), false);

  ToolbarMain.AddDropdown(12, PopupToolbarCase);
  ToolbarMain.AddDropdown(13, PopupToolbarComment);
  ToolbarMain.AddButton(14, @DoToolbarClick, 'opt', 'Options Editor', 'module=cuda_options_editor;cmd=dlg_cuda_options;', false);
end;


const
  cSidebarIconTree     = 0;
  cSidebarIconConsole  = 1;
  cSidebarIconOutput   = 2;
  cSidebarIconValidate = 3;
  cSidebarIconFind     = 4;
  cSidebarIconMenu     = 5;

procedure TfmMain.DoOps_LoadSidebarIcons;
var
  Parts: TRegexParts;
  Str: string;
  NTick: QWord;
begin
  NTick:= GetTickCount64;

  SRegexFindParts('.+_(\d+)x(\d+)', UiOps.SidebarTheme, Parts);

  ImageListSide.Width:= StrToIntDef(Parts[1].Str, ImageListSide.Width);
  ImageListSide.Height:= StrToIntDef(Parts[2].Str, ImageListSide.Height);
  ImageListSide.Clear;

  Str:= AppDir_DataSidebarIcons+DirectorySeparator+UiOps.SidebarTheme;
  if not DirectoryExists(Str) then
  begin
    MsgLogConsole(Format(msgCannotFindData, [Str]));
    ToolbarSideMid.UpdateControls;
    exit;
  end;

  Str+= DirectorySeparator;

  UpdateImagelistWithIconFromFile(ImageListSide, Str+'tree.png');
  UpdateImagelistWithIconFromFile(ImageListSide, Str+'console.png');
  UpdateImagelistWithIconFromFile(ImageListSide, Str+'output.png');
  UpdateImagelistWithIconFromFile(ImageListSide, Str+'validate.png');
  UpdateImagelistWithIconFromFile(ImageListSide, Str+'find.png');
  UpdateImagelistWithIconFromFile(ImageListSide, Str+'menu.png');

  if UiOps.LogConsoleDetailedStartupTime then
  begin
    NTick:= GetTickCount64-NTick;
    MsgLogConsole(Format('Loaded sidebar icons: %dms', [NTick]));
  end;
end;


procedure TfmMain.DoOps_LoadCodetreeIcons;
var
  Parts: TRegexParts;
  SPath, SItem: string;
  Sep: TATStringSeparator;
begin
  SRegexFindParts('.+_(\d+)x(\d+)', UiOps.TreeTheme, Parts);

  if not Assigned(ImageListTree) then
    raise Exception.Create('ImageListTree nil');
  ImageListTree.Width:= StrToIntDef(Parts[1].Str, 16);
  ImageListTree.Height:= StrToIntDef(Parts[2].Str, 16);
  ImageListTree.Clear;

  SPath:= AppDir_DataCodetreeIcons+DirectorySeparator+UiOps.TreeTheme;
  if not DirectoryExists(SPath) then
  begin
    MsgLogConsole(Format(msgCannotFindData, [SPath]));
    exit;
  end;
  SPath+= DirectorySeparator;

  Sep.Init(UiOps.TreeIconFilenames);
  while Sep.GetItemStr(SItem) do
    UpdateImagelistWithIconFromFile(ImageListTree, SPath+SItem+'.png');
end;

procedure TfmMain.DoOps_LoadToolbarIcons;
var
  Parts: TRegexParts;
  Str: string;
  Img: TImageList;
  NTick: QWord;
begin
  NTick:= GetTickCount64;

  SRegexFindParts('.+_(\d+)x(\d+)', UiOps.ToolBarTheme, Parts);

  Str:= AppDir_DataToolbarIcons+DirectorySeparator+UiOps.ToolBarTheme;
  if not DirectoryExists(Str) then
  begin
    MsgLogConsole(Format(msgCannotFindData, [Str]));
    Exit;
  end;

  Img:= ToolbarMain.Images;
  Img.Width:= StrToIntDef(Parts[1].Str, 24);
  Img.Height:= StrToIntDef(Parts[2].Str, 24);
  Img.Clear;

  Str+= DirectorySeparator;
  UpdateImagelistWithIconFromFile(Img, Str+'f_new.png');
  UpdateImagelistWithIconFromFile(Img, Str+'f_open.png');
  UpdateImagelistWithIconFromFile(Img, Str+'f_save.png');
  UpdateImagelistWithIconFromFile(Img, Str+'e_cut.png');
  UpdateImagelistWithIconFromFile(Img, Str+'e_copy.png');
  UpdateImagelistWithIconFromFile(Img, Str+'e_paste.png');
  UpdateImagelistWithIconFromFile(Img, Str+'e_undo.png');
  UpdateImagelistWithIconFromFile(Img, Str+'e_redo.png');
  UpdateImagelistWithIconFromFile(Img, Str+'unpri.png');
  UpdateImagelistWithIconFromFile(Img, Str+'map.png');
  UpdateImagelistWithIconFromFile(Img, Str+'indent.png');
  UpdateImagelistWithIconFromFile(Img, Str+'unindent.png');
  UpdateImagelistWithIconFromFile(Img, Str+'case.png');
  UpdateImagelistWithIconFromFile(Img, Str+'comment.png');
  UpdateImagelistWithIconFromFile(Img, Str+'opt.png');

  if UiOps.LogConsoleDetailedStartupTime then
  begin
    NTick:= GetTickCount64-NTick;
    MsgLogConsole(Format('Loaded toolbar icons: %dms', [NTick]));
  end;
end;


procedure TfmMain.InitSidebar;
begin
  ToolbarSideTop.AddButton(cSidebarIconMenu, @DoSidebar_MainMenuClick, msgPanelMenu_Init, msgPanelMenu_Init, '', false);

  ToolbarSideMid.AddButton(cSidebarIconFind, @DoBottom_FindClick, msgPanelSearch_Init, msgPanelSearch_Init, '', false);
  ToolbarSideMid.AddSep;

  AppPanels[cPaneSide].Add(msgPanelTree_Init, cSidebarIconTree, PtrInt(Pointer(PanelCodeTreeAll)), @DoSidebar_OnShowCodeTree);

  AppPanels[cPaneOut].Add(msgPanelConsole_Init, cSidebarIconConsole, PtrInt(Pointer(fmConsole)), nil);
  AppPanels[cPaneOut].Add(msgPanelOutput_Init, cSidebarIconOutput, PtrInt(Pointer(ListboxOut)), nil);
  AppPanels[cPaneOut].Add(msgPanelValidate_Init, cSidebarIconValidate, PtrInt(Pointer(ListboxVal)), nil);
end;


procedure TfmMain.InitPopupTabSize;
var
  Ed: TATSynEdit;
  Msg: string;
  NTab, i: integer;
  mi: TMenuItem;
begin
  if PopupTabSize=nil then
  begin
    PopupTabSize:= TPopupMenu.Create(Self);

    mi:= TMenuItem.Create(Self);
    mi.Caption:= '-';
    PopupTabSize.Items.Add(mi);

    mnuTabsizeSpace:= TMenuItem.Create(Self);
    mnuTabsizeSpace.OnClick:= @mnuTabsizeSpaceClick;
    PopupTabSize.Items.Add(mnuTabsizeSpace);

    mi:= TMenuItem.Create(Self);
    mi.Caption:= '-';
    PopupTabSize.Items.Add(mi);

    mnuTabsizeConvTabs:= TMenuItem.Create(Self);
    PopupTabSize.Items.Add(mnuTabsizeConvTabs);

    mnuTabsizeConvSpaces:= TMenuItem.Create(Self);
    PopupTabSize.Items.Add(mnuTabsizeConvSpaces);

    for i:= cMenuTabsizeMax downto cMenuTabsizeMin do
    begin
      mi:= TMenuItem.Create(Self);
      mi.Caption:= IntToStr(i);
      mi.Tag:= i;
      mi.OnClick:= @MenuTabsizeClick;
      mnuTabsizesValue[i]:= mi;
      PopupTabSize.Items.Insert(0, mi);
    end;
  end;

  mnuTabsizeSpace.Caption:= msgTabsizeUseSpaces;
  mnuTabsizeConvSpaces.Caption:= msgTabsizeConvSpaces;
  mnuTabsizeConvTabs.Caption:= msgTabsizeConvTabs;

  UpdateMenuItemHotkey(mnuTabsizeConvSpaces, cmd_ConvertSpacesToTabsLeading);
  UpdateMenuItemHotkey(mnuTabsizeConvTabs, cmd_ConvertTabsToSpacesLeading);

  Ed:= CurrentEditor;
  if Ed.OptTabSpaces then
    Msg:= msgStatusbarTextSpaces
  else
    Msg:= msgStatusbarTextTab;
  NTab:= Ed.OptTabSize;

  for i:= cMenuTabsizeMin to cMenuTabsizeMax do
  begin
    mnuTabsizesValue[i].Caption:= Msg+': '+IntToStr(i);
    mnuTabsizesValue[i].Checked:= NTab=i;
  end;

  mnuTabsizeSpace.Checked:= Ed.OptTabSpaces;
end;


procedure TfmMain.InitPopupTree;
var
  mi: TMenuItem;
begin
  if PopupTree=nil then
  begin
    PopupTree:= TPopupMenu.Create(Self);

    mnuTreeFoldAll:= TMenuItem.Create(Self);
    mnuTreeFoldAll.OnClick:= @mnuTreeFoldAllClick;
    PopupTree.Items.Add(mnuTreeFoldAll);

    mnuTreeUnfoldAll:= TMenuItem.Create(Self);
    mnuTreeUnfoldAll.OnClick:= @mnuTreeUnfoldAllClick;
    PopupTree.Items.Add(mnuTreeUnfoldAll);

    mnuTreeFoldLevel:= TMenuItem.Create(Self);
    PopupTree.Items.Add(mnuTreeFoldLevel);

    mnuTreeFold2:= TMenuItem.Create(Self);
    mnuTreeFold2.Caption:= '2';
    mnuTreeFold2.OnClick:= @mnuTreeFold2Click;
    mnuTreeFoldLevel.Add(mnuTreeFold2);

    mnuTreeFold3:= TMenuItem.Create(Self);
    mnuTreeFold3.Caption:= '3';
    mnuTreeFold3.OnClick:= @mnuTreeFold3Click;
    mnuTreeFoldLevel.Add(mnuTreeFold3);

    mnuTreeFold4:= TMenuItem.Create(Self);
    mnuTreeFold4.Caption:= '4';
    mnuTreeFold4.OnClick:= @mnuTreeFold4Click;
    mnuTreeFoldLevel.Add(mnuTreeFold4);

    mnuTreeFold5:= TMenuItem.Create(Self);
    mnuTreeFold5.Caption:= '5';
    mnuTreeFold5.OnClick:= @mnuTreeFold5Click;
    mnuTreeFoldLevel.Add(mnuTreeFold5);

    mnuTreeFold6:= TMenuItem.Create(Self);
    mnuTreeFold6.Caption:= '6';
    mnuTreeFold6.OnClick:= @mnuTreeFold6Click;
    mnuTreeFoldLevel.Add(mnuTreeFold6);

    mnuTreeFold7:= TMenuItem.Create(Self);
    mnuTreeFold7.Caption:= '7';
    mnuTreeFold7.OnClick:= @mnuTreeFold7Click;
    mnuTreeFoldLevel.Add(mnuTreeFold7);

    mnuTreeFold8:= TMenuItem.Create(Self);
    mnuTreeFold8.Caption:= '8';
    mnuTreeFold8.OnClick:= @mnuTreeFold8Click;
    mnuTreeFoldLevel.Add(mnuTreeFold8);

    mnuTreeFold9:= TMenuItem.Create(Self);
    mnuTreeFold9.Caption:= '9';
    mnuTreeFold9.OnClick:= @mnuTreeFold9Click;
    mnuTreeFoldLevel.Add(mnuTreeFold9);

    mi:= TMenuItem.Create(Self);
    mi.Caption:= '-';
    PopupTree.Items.Add(mi);

    mnuTreeSorted:= TMenuItem.Create(Self);
    mnuTreeSorted.OnClick:= @mnuTreeSortedClick;
    PopupTree.Items.Add(mnuTreeSorted);
  end;

  mnuTreeFoldAll.Caption:= cStrMenuitemFoldAll;
  mnuTreeUnfoldAll.Caption:= cStrMenuitemUnfoldAll;
  mnuTreeFoldLevel.Caption:= cStrMenuitemFoldLevel;
  mnuTreeSorted.Caption:= msgTreeSorted;

  mnuTreeSorted.Checked:= CodeTree.Tree.SortType<>stNone;
end;

procedure TfmMain.InitPopupPicScale;
const
  cSizes: array[0..8] of integer =
    (-1, 33, 50, 100, 150, 200, 500, 1000, 1500);
var
  mi: TMenuItem;
  i: integer;
begin
  if PopupPicScale=nil then
  begin
    PopupPicScale:= TPopupMenu.Create(Self);
    for i:= Low(cSizes) to High(cSizes) do
    begin
      mi:= TMenuItem.Create(Self);
      if cSizes[i]=-1 then
        mi.Caption:= msgDefault
      else
        mi.Caption:= IntToStr(cSizes[i])+'%';
      mi.Tag:= cSizes[i];
      mi.OnClick:= @MenuPicScaleClick;
      PopupPicScale.Items.Add(mi);
    end;
  end;
end;

